International Securities Identification Number

An International Securities Identification Number (ISIN) uniquely identifies a security. Its structure is defined in ISO 6166. Securities for which ISINs are issued include bonds, commercial paper, equities and warrants. The ISIN code is a 12-character alpha-numerical code that does not contain information characterizing financial instruments but serves for uniform identification of a security at trading and settlement.

Securities to which ISINs can be issued include debt securities, shares, options, derivatives and futures. The ISIN identifies the security, not the exchange (if any) on which it trades; it is not a ticker symbol. For instance, Daimler AG stock trades through almost 30 trading platforms and exchanges worldwide, and is priced in five different currencies; it has the same ISIN on each, though not the same ticker symbol. ISIN cannot specify a particular trading location in this case, and another identifier, typically MIC (Market Identification Code) or the three-letter exchange code, will have to be specified in addition to the ISIN. The Currency of the trade will also be required to uniquely identify the instrument using this method.

Contents

Description

An ISIN consists of three parts: Generally, a two letter country code, a nine character alpha-numeric national security identifier, and a single check digit. The country code is the ISO 3166-1 alpha-2 code for the country of issue, which is not necessarily the country where the issuing company is domiciled. International securities cleared through Clearstream or Euroclear, which are Europe-wide, use "XS" as the country code.

Issuance

The ISIN is based on the National Securities Identifying Number, or NSIN, assigned by governing bodies in each country, known as the national numbering agency (NNA). The NNA's are co-ordinated through the Association of National Numbering Agences, ANNA[1]. ISIN and CFI information can be accessed through the ANNA Service Bureau[2], run by Standard and Poor's and SIX Telekurs.

The NSIN element of the ISIN can be up to 9 digits long. Shorter numbers are padded with leading zeros before the addition of the county code and a check digit transform the NSIN to an ISIN.

In North America the NNA is the CUSIP organization, meaning that CUSIPs can easily be converted into ISINs by adding the US or CA country code to the beginning of the existing CUSIP code and adding an additional check digit at the end. In the United Kingdom and Ireland the NNA is the London Stock Exchange and the NSIN is the SEDOL, converted in a similar fashion . Swiss ISINs are issued by SIX Telekurs and are based on the Valor Number. Most other countries use similar conversions, but if no country NNA exists then regional NNAs are used instead.

ISIN Calculation Methodology

The procedure for calculating ISIN check digits is similar to the "Modulus 10 Double Add Double" technique used in CUSIPs. To calculate the check digit, first convert any letters to numbers by adding their ordinal position in the alphabet to 9, such that A = 10 and M = 22. Starting with the right most digit, every other digit is multiplied by two. (For CUSIP check digits, these two steps are reversed.) The resulting string of digits (numbers greater than 9 becoming two separate digits) are added up. Subtract this sum from the smallest number ending with zero that is greater than or equal to it: this gives the check digit, which is also known as the ten's complement of the sum modulo 10. That is, the resulting sum, including the check-digit, is a multiple of 10.

ISINs are slowly being introduced worldwide. At present, trading, clearing and settlement systems in many countries have adopted ISINs as a secondary measure of identifying securities. Additionally, some of those countries, mainly in Europe, have moved to using ISINs as their primary means of identifying securities.

Conversion table for characters is :

A = 10 F = 15 K = 20 P = 25 U = 30 Z = 35
B = 11 G = 16 L = 21 Q = 26 V = 31
C = 12 H = 17 M = 22 R = 27 W = 32
D = 13 I = 18 N = 23 S = 28 X = 33
E = 14 J = 19 O = 24 T = 29 Y = 34

In other words; Take the ASCII code for the capital letter and subtract 55

Excel VBA Function for validating an ISINCode:

Public Function ISINCODE(ByVal sISINCode As String) As Boolean
 
   'Jelle-Jeroen Lamkamp 28 Apr 2008 
   
   Dim i As Integer: Dim iTotalScore As Integer
   Dim s As String: Dim sDigits As String
 
   sISINCode = UCase(Trim(sISINCode))
 
   If Len(sISINCode) <> 12 Then Exit Function
 
   If MID(sISINCode,1,1) < "A" Or MID(sISINCode,1,1) > "Z" Then Exit Function
   If MID(sISINCode,2,1) < "A" Or MID(sISINCode,2,1) > "Z" Then Exit Function
 
   sDigits = ""
 
   For i = 1 To 11
       s = Mid(sISINCode, i, 1)
       If s >= "0" And s <= "9" Then
          sDigits = sDigits & s
       ElseIf s >= "A" And s <= "Z" Then
          sDigits = sDigits & CStr(Asc(s) - 55)
       Else
          Exit Function
       End If
   Next i
 
   sDigits = StrReverse(sDigits)
 
   iTotalScore = 0
 
   For i = 1 To Len(sDigits)
       iTotalScore = iTotalScore + CInt(Mid(sDigits, i, 1))
       If i Mod 2 = 1 Then
          iTotalScore = iTotalScore + CInt(Mid(sDigits, i, 1))
          If CInt(Mid(sDigits, i, 1)) > 4 Then
             iTotalScore = iTotalScore - 9
          End If
       End If
   Next i
 
   If (10 - (iTotalScore Mod 10)) Mod 10 = CInt(Mid(sISINCode, 12, 1)) Then ISINCODE = True
 
End Function

TSQL codes for validating an ISINCode:

-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:	Pang Chong Peng
-- Create date: 20/7/2010
-- Description:	CheckSum for ISIN code
-- =============================================
CREATE FUNCTION [dbo].[fn_IsISINValid] ( @ISINCode  AS  NVARCHAR(20))
RETURNS BIT
AS
BEGIN
 
	DECLARE @i AS INT;
	DECLARE @iTotalScore AS INT;
	DECLARE @s AS INT;
	DECLARE @sDigit AS VARCHAR(22); /* Edit 101004 csouto: Needs to be 22 characters long so it can validate Isin Codes for 'Lotes PadrĂ£o' */
 
        SELECT @ISINCode = UPPER(@ISINCode);
 
	IF LEN (@ISINCode) != 12
		RETURN 0;
 
	IF ASCII(SUBSTRING(@ISINCode, 1, 1)) < ASCII('A') OR ASCII(SUBSTRING(@ISINCode, 1, 1)) > ASCII('Z')
		RETURN 0;
 
	IF ASCII(SUBSTRING(@ISINCode, 2, 1)) < ASCII('A') OR ASCII(SUBSTRING(@ISINCode, 2, 1)) > ASCII('Z')
		RETURN 0;
 
	IF (ISNUMERIC(SUBSTRING(@ISINCode, 12, 1)) = 0) -- Check that the checksum is numeric
		RETURN 0;	
 
	SELECT @sDigit = '';
 
	SELECT @i = 1;
	WHILE (@i <= 11)
	BEGIN
		SELECT @s = ASCII(SUBSTRING(@ISINCode, @i, 1))
		IF @s >= ASCII('0') AND @s <= ASCII('9') 
			SELECT @sDigit = @sDigit + SUBSTRING(@ISINCode, @i, 1);
		ELSE IF @s >= ASCII('A') AND @s <= ASCII('Z') 
			SELECT @sDigit = @sDigit + CONVERT(VARCHAR(2), @s - 55);
		ELSE
			BREAK;		
		SELECT @i = @i + 1;				
	END
 
	SELECT @sDigit = REVERSE(@sDigit);
	SELECT @iTotalScore = 0;
	SELECT @i = 1;
 
	WHILE (@i <= LEN(@sDigit))
	BEGIN
		SELECT @iTotalScore = @iTotalScore + CONVERT(INT, SUBSTRING(@sDigit, @i, 1))
		 IF @i%2 = 1
		BEGIN
			SELECT @iTotalScore = @iTotalScore + CONVERT(INT, SUBSTRING(@sDigit, @i, 1))
			IF  CONVERT(INT, (SUBSTRING(@sDigit, @i, 1))) > 4
			BEGIN
				SELECT @iTotalScore = @iTotalScore - 9;
			END 
		END
 
		SELECT @i = @i + 1;
	END
 
 
	IF (10 - (@iTotalScore%10))%10 = CONVERT (INT,(SUBSTRING(@ISINCode, 12, 1)))
		RETURN 1;
 
	RETURN 0;
 
END

JavaScript codes for validating an ISINCode:

function checkISINCODE(sISINCode){
	var i, iTotalScore, s, sDigits;
 
	if( sISINCode.length != 12){
		return false;
	}
 
	if( sISINCode.charCodeAt(0) < "A".charCodeAt(0) || 
		sISINCode.charCodeAt(0) > "Z".charCodeAt(0) ){
		return false;
	}
	if( sISINCode.charCodeAt(1) < "A".charCodeAt(0) ||
		sISINCode.charCodeAt(1) > "Z".charCodeAt(0) ){
		return false;
	}
 
	sDigits = "";
 
	for(var i = 0; i < 11; i++){
	    sDigits += parseInt(sISINCode.charAt(i), 36);
	}
 
	var sDigits = sDigits.split("").reverse().join("");
 
	var iTotalScore = 0;
 
	for(var i = 0; i< sDigits.length; i++){
	    iTotalScore += parseInt(sDigits.charAt(i));
	    if (i % 2 == 0){
	       iTotalScore += parseInt(sDigits.charAt(i));
	       if ( parseInt(sDigits.charAt(i)) > 4 ){
	          iTotalScore -= 9;
	       }
	    }
	}
 
	return (10 - (iTotalScore % 10)) % 10 == parseInt(sISINCode.charAt(11));
}

Java code for validating an ISINCode:

  private static final Pattern ISIN_PATTERN = Pattern.compile("[A-Z]{2}([A-Z0-9]){9}[0-9]");
 
  public static boolean checkIsinCode(String isin) {
    if (isin == null) {
      return false;
    }
    if (!ISIN_PATTERN.matcher(isin).matches()) {
      return false;
    }
 
    StringBuffer digits = new StringBuffer();
    for (int i = 0; i < 11; i++) {
      digits.append(Character.digit(isin.charAt(i), 36));
    }
    digits.reverse();
    int sum = 0;
    for (int i = 0; i < digits.length(); i++) {
      int digit = Character.digit(digits.charAt(i));
      if (i % 2 == 0) {
        digit *= 2;
      }
      sum += digit / 10;
      sum += digit % 10;
    }
 
    int checkDigit = Character.digit(isin.charAt(11));
    int tensComplement = (sum % 10 == 0) ? 0 : ((sum / 10) + 1) * 10 - sum;
    return checkDigit == tensComplement;
  }

C# Code for validating an ISINCode:

using System;
using System.Text.RegularExpressions;
 
namespace ISIN
{
    public static class ISINChecker
    {
        public static bool CheckIsinCode(string isin)
        {
            Regex ISIN_PATTERN = new Regex(@"[A-Z]{2}([A-Z0-9]){9}[0-9]");
            if (isin == null)
            {
                return false;
            }
            if (!ISIN_PATTERN.IsMatch(isin))
            {
                return false;
            }
 
            int[] digits = new int[22];
            int index = 0;
            for (int i = 0; i < 11; i++)
            {
                char c = isin[i];
                if (c >= '0' && c <= '9')
                {
                    digits[index++] = c - '0';
                }
                else if (c >= 'A' && c <= 'Z')
                {
                    int n = c - 'A' + 10;
                    int tens = n / 10;
                    if (tens != 0)
                    {
                        digits[index++] = tens;
                    }
                    digits[index++] = n % 10;
                }
                else
                {
                    // Not a digit or upper-case letter.
                    return false;
                }
            }
            int sum = 0;
            for (int i = 0; i < index; i++)
            {
                int digit = digits[index - 1 - i];
                if (i % 2 == 0)
                {
                    digit *= 2;
                }
                sum += digit / 10;
                sum += digit % 10;
            }
 
            int checkDigit = isin[11] - '0';
            int tensComplement = (sum % 10 == 0) ? 0 : ((sum / 10) + 1) * 10 - sum;
            return checkDigit == tensComplement;
        }
    }
}

Python code for validating ISIN codes

import re
 
def checkISIN(value):
    value = value.strip().upper()
    m = re.match('^([A-Z][A-Z])([A-Z0-9]{9}\d)$', value)
    if not m:
        return False
    sum_digits_str = ''.join(str(int(c, 36)) for c in value[:11])
    total_sum = 0
    parity = len(sum_digits_str) % 2
    for n, c in enumerate(sum_digits_str):
        a = int(c)
        if n % 2 != parity:
            a = a * 2
        total_sum += a / 10
        total_sum += a % 10
    check_digit = (10 - (total_sum % 10)) % 10
    return value[11] == unicode(check_digit)
 
if __name__ == "__main__":
    for i in [
        'US0378331005',
        'AU0000XVGZA3',
        'GB0002634946']:
        print i, checkISIN(i)

SAS code for validating ISIN codes

/* Aitor Olasagasti Alonso 2011-04-19 */
/* SAS 8.2 and SAS 9.X compatible */
data trueIsin;
    set isinTable;
    length allCode $24;
    ilegal = 0;
    if length(isin) ^= 12 then delete;
    lastNum = substr(isin, 12, 1);
    code = rank(lastNum);
    if not (code >= 48 and code =< 57) then delete;
    do i = 1 to 11;
        code = rank(substr(isin, i, 1));
        if code <48 or (code > 57 and code < 65) or code > 90 then ilegal = 1;
        if (i = 1 or i = 2) and (code < 65 or code > 90) then ilegal = 1;
        if code >= 65 and code =< 90 then do;
            code = code-55;
            allCode = compress(allCode) || compress(put(code, best.)); 
        end;
        else do;
            allCode = compress(allCode) || substr(isin, i, 1);
        end;	
    end;
    if ilegal then delete;
    suma = 0;
    rAllCode =  reverse(trim(allCode));
    rlength = length(rAllCode);
    do i = 1 to rlength;
        numb = input(substr(rAllCode, i, 1), best.);
        if mod(i, 2) then do;
            numb = numb * 2;
            if numb / 10 >= 1 then do;
                suma = suma + mod(numb, 10) + 1;
            end;
            else do;
                suma = suma + (numb);
            end;
        end;
        else do;
            suma = suma + numb;
        end;
    end;
    modSum = mod(suma, 10);
    total = mod(10 - modSum, 10);
    if total ^= input(lastNum, best.) then delete;
run;

PHP Code for validating an ISINCode:

function isIsin($isin) {
	if (strlen(trim($isin))) {
		$cle = substr($isin, -1);
		$isinLeft = substr($isin, 0, strlen($isin)-1);
		$letter2number = array('A'=>10, 'B'=>11, 'C'=>12, 'D'=>13, 'E'=>14, 'F'=>15, 'G'=>16, 'H'=>17, 'I'=>18, 'J'=>19, 'K'=>20, 'L'=>21, 'M'=>22, 'N'=>23, 'O'=>24, 'P'=>25, 'Q'=>26, 'R'=>27, 'S'=>28, 'T'=>29, 'U'=>30, 'V'=>31, 'W'=>32, 'X'=>33, 'Y'=>34, 'Z'=>35);
		$isinConvertion = strtr($isinLeft, $letter2number);
		$sum = '';
		$sumFinal = 0;
		for($i=0; $i<strlen($isinConvertion); ++$i) $sum .= (($i % 2) ? 1 : 2)*$isinConvertion[$i];
		for($i=0; $i<strlen($sum); ++$i) $sumFinal += $sum[$i];
		if ($sumFinal % 10){
			$cleVerif = ((int)($sumFinal/10) + 1)*10-$sumFinal;
		} else {
			$cleVerif = 0;
		}
		if ($cle == $cleVerif) {
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
}

Examples

Apple Inc.

Apple Inc.: ISIN US0378331005, expanded from CUSIP 037833100 The main body of the ISIN is the original CUSIP, assigned in the 1970s. The country code "US" has been added on the front, and an additional check digit at the end. The country code indicates the country in which the issuer is domiciled. The check digit is calculated in this way...

Convert any letters to numbers:

U = 30, S = 28. US037833100 -> 3028037833100.

Collect odd and even characters:

3028037833100 = (3, 2, 0, 7, 3, 1, 0), (0, 8, 3, 8, 3, 0)

Multiply the group containing the rightmost character (which is the FIRST group) by 2:

(6, 4, 0, 14, 6, 2, 0)

Add up the individual digits:

(6 + 4 + 0 + (1 + 4) + 6 + 2 + 0) + (0 + 8 + 3 + 8 + 3 + 0) = 45

Take the 10s modulus of the sum:

45 mod 10 = 5

Subtract from 10:

10 - 5 = 5

Take the 10s modulus of the result (this final step is important in the instance where the modulus of the sum is 0, as the resulting check digit would be 10).

5 mod 10 = 5

So the ISIN check digit is five.

Treasury Corporation of Victoria

TREASURY CORP VICTORIA 5 3/4% 2005-2016: ISIN AU0000XVGZA3

Convert any letters to numbers:

A = 10, G = 16, U = 30, V = 31, X = 33, Z = 35. AU0000XVGZA -> 103000003331163510.

Collect odd and even characters:

103000003331163510 = (1, 3, 0, 0, 3, 3, 1, 3, 1), (0, 0, 0, 0, 3, 1, 6, 5, 0)

Multiply the group containing the rightmost character (which is the SECOND group) by 2:

(0, 0, 0, 0, 6, 2, 12, 10, 0)

Add up the individual digits:

(1 + 3 + 0 + 0 + 3 + 3 + 1 + 3 + 1) + (0 + 0 + 0 + 0 + 6 + 2 + (1 + 2) + (1 + 0) + 0) = 27

Take the 10s modulus of the sum:

27 mod 10 = 7

Subtract from 10:

10 - 7 = 3

Take the 10s modulus of the result (this final step is important in the instance where the modulus of the sum is 0, as the resulting check digit would be 10).

3 mod 10 = 3

So the ISIN check digit is three.

BAE Systems

BAE Systems: ISIN GB0002634946, expanded from SEDOL 0263494

The main body is the SEDOL, padded on the front with the addition of two zeros. The country code "GB" is then added on the front, and the check digit on the end as in the example above.

References

  1. ^ http://www.anna-web.com
  2. ^ http://www.annaservice.com